# -*- coding: utf-8 -*-
"""
Created on
@Time: 2024/12/20 15:58
@Author: Mr.Z
@contact: <QQ:40061980>
@contact: bob@pheks.com
@File: encrypt.py
@IDE: PyCharm
@Python Version：
"""

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad

"""
 该模块用于给密码加密，并通过加密后的数据进行解密，解密后为原来密码
 - 要求用户输入密码
 - 对用户输入的密码进行加密
 - 将加密后的数据以十六进制打印出来

 - 使用加密后的数据进行解密（如果使用十六进制需要先将十六进制数据还原）
 - 打印出解密后的密码（用户可以检查该密码是否是自己输入的密码）

 注意：
 正常情况下，可以对用户输入的密码进行加密后，将加密后的密码以及生成的密钥保存在数据库或配置文件中，
 并在需要解密时，通过密钥对加密后的密码进行解密，得到原来输入的密码。
"""


# 加密函数, 加密后的密文可以通过decrypt_password函数解密
def encrypt_password(password, key):
    # 确保key的长度是AES要求的长度（16, 24, 或 32字节）
    if len(key) not in [16, 24, 32]:
        raise ValueError("Key must be either 16, 24, or 32 bytes long")

    # AES要求数据长度是块大小的倍数（对于AES是16字节）
    cipher = AES.new(key, AES.MODE_CBC)
    ct_bytes = cipher.encrypt(pad(password.encode('utf-8'), AES.block_size))  # 加密密码并填充
    iv = cipher.iv  # 初始化向量
    print(f'iv: {iv}, \nct_bytes: {ct_bytes}')
    return iv + ct_bytes  # 返回iv和密文，以便后续解密


# 解密函数，传入加密后的密文和密钥（非16进制的密码和密钥）
def decrypt_password(ciphertext, key):
    print(f'ciphertext: {ciphertext}\n')
    print(f'key: {key}\n')
    iv = ciphertext[:AES.block_size]  # 提取iv
    print(f'iv: {iv}, \nct_bytes: {ciphertext[AES.block_size:]}\n')
    ct = ciphertext[AES.block_size:]  # 提取密文
    print(f'ct: {ct}, \nct_bytes: {ct}\n')
    cipher = AES.new(key, AES.MODE_CBC, iv)  # 创建一个新的AES对象
    pt = unpad(cipher.decrypt(ct), AES.block_size)  # 解密密文
    return pt.decode('utf-8')  # 返回解密后的密码


import bcrypt  # 导入bcrypt模块


# 使用哈希对密码进行不可逆加密
def hash_password(password):
    salt = bcrypt.gensalt()  # 生成一个随机的salt
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)  # 使用bcrypt对密码进行加密
    return hashed_password.decode('utf-8')  # 返回加密后的密码


# 验证密码是否正确
def verify_password(original_password, hashed_password):
    return bcrypt.checkpw(original_password.encode('utf-8'), hashed_password.encode('utf-8'))  # 验证密码是否正确


# 生成一个随机的密钥（这里为了示例简单性，实际使用中应该安全地存储和分发密钥）
key = get_random_bytes(16)  # 生成一个16字节的随机密钥
print(f"系统随机生成的16字节Key: {key}\n")

if __name__ == '__main__':
    print('---- 提示：输入密码后按回车键执行加密码。----')
    password = input("请输入您的密码: ")  # 输入密码
    encrypted = encrypt_password(password, key)  # 加密密码
    print(f'加密后的密码（原始数据）: {encrypted}\n')
    decrypted = decrypt_password(encrypted, key)  # 解密密码

    hashed_password = hash_password(password)  # 使用哈希对密码进行不可逆加密
    print(f"加密后的密码（哈希后）: {hashed_password}\n")

    # 验证哈希后的密码是否正确
    if verify_password(password, hashed_password):
        print("密码验证成功！")
    else:
        print("密码验证失败！")

    print('\n\n\n\n\n\n')

    print('--------------- 以下内容请妥善保管，请勿泄漏！ ---------------')
    print("-- 加密后的密码（解析为16进制）:", encrypted.hex())  # 打印加密后的数据（以十六进制形式）
    print("-- 密码长度:", len(encrypted.hex()), "位")
    print("-- Key（解析为16进制）:", key.hex())  # 打印密钥（以十六进制形式）
    print("-- 解密后的原密码:", decrypted)  # 打印解密后的密码
    print(f"-- 您输入的原始密码：{password}")  # 打印用户输入的原始密码用于和解密后的密码比较
    print('---------------- 以上内容请妥善保管，请勿泄漏！ -----------------')
